//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension Grafana {
    // MARK: Enums

    public enum AccountAccessType: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Indicates that the customer is using Grafana to monitor resources in their current account.
        case currentAccount = "CURRENT_ACCOUNT"
        /// Indicates that the customer is using Grafana to monitor resources in organizational units.
        case organization = "ORGANIZATION"
        public var description: String { return self.rawValue }
    }

    public enum AuthenticationProviderTypes: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Indicates that AMG workspace has AWS SSO enabled as its authentication provider.
        case awsSso = "AWS_SSO"
        /// Indicates that the AMG workspace has SAML enabled as its authentication provider.
        case saml = "SAML"
        public var description: String { return self.rawValue }
    }

    public enum DataSourceType: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Amazon OpenSearch Service
        case amazonOpensearchService = "AMAZON_OPENSEARCH_SERVICE"
        /// Amazon Athena
        case athena = "ATHENA"
        /// CloudWatch Logs
        case cloudwatch = "CLOUDWATCH"
        /// Managed Prometheus
        case prometheus = "PROMETHEUS"
        /// Redshift
        case redshift = "REDSHIFT"
        /// IoT SiteWise
        case sitewise = "SITEWISE"
        /// Timestream
        case timestream = "TIMESTREAM"
        /// IoT TwinMaker
        case twinmaker = "TWINMAKER"
        /// X-Ray
        case xray = "XRAY"
        public var description: String { return self.rawValue }
    }

    public enum LicenseType: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Grafana Enterprise License.
        case enterprise = "ENTERPRISE"
        /// Grafana Enterprise Free Trial License.
        case enterpriseFreeTrial = "ENTERPRISE_FREE_TRIAL"
        public var description: String { return self.rawValue }
    }

    public enum NotificationDestinationType: String, CustomStringConvertible, Codable, _SotoSendable {
        /// AWS Simple Notification Service
        case sns = "SNS"
        public var description: String { return self.rawValue }
    }

    public enum PermissionType: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Customer Managed
        case customerManaged = "CUSTOMER_MANAGED"
        /// Service Managed
        case serviceManaged = "SERVICE_MANAGED"
        public var description: String { return self.rawValue }
    }

    public enum Role: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Role Admin.
        case admin = "ADMIN"
        /// Role Editor.
        case editor = "EDITOR"
        /// Role Viewer.
        case viewer = "VIEWER"
        public var description: String { return self.rawValue }
    }

    public enum SamlConfigurationStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Indicates that SAML on an AMG workspace is enabled and has been configured.
        case configured = "CONFIGURED"
        /// Indicates that SAML on an AMG workspace is enabled but has not been configured.
        case notConfigured = "NOT_CONFIGURED"
        public var description: String { return self.rawValue }
    }

    public enum UpdateAction: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Add permissions.
        case add = "ADD"
        /// Revoke permissions.
        case revoke = "REVOKE"
        public var description: String { return self.rawValue }
    }

    public enum UserType: String, CustomStringConvertible, Codable, _SotoSendable {
        /// SSO group.
        case ssoGroup = "SSO_GROUP"
        /// SSO user.
        case ssoUser = "SSO_USER"
        public var description: String { return self.rawValue }
    }

    public enum WorkspaceStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        /// Workspace is active.
        case active = "ACTIVE"
        /// Workspace is being created.
        case creating = "CREATING"
        /// Workspace creation failed.
        case creationFailed = "CREATION_FAILED"
        /// Workspace is being deleted.
        case deleting = "DELETING"
        /// Workspace deletion failed.
        case deletionFailed = "DELETION_FAILED"
        /// Workspace is in an invalid state, it can only and should be deleted.
        case failed = "FAILED"
        /// Failed to remove enterprise license from workspace.
        case licenseRemovalFailed = "LICENSE_REMOVAL_FAILED"
        /// Workspace update failed.
        case updateFailed = "UPDATE_FAILED"
        /// Workspace is being updated.
        case updating = "UPDATING"
        /// Workspace upgrade failed.
        case upgradeFailed = "UPGRADE_FAILED"
        /// Workspace is being upgraded to enterprise.
        case upgrading = "UPGRADING"
        public var description: String { return self.rawValue }
    }

    public enum IdpMetadata: AWSEncodableShape & AWSDecodableShape, _SotoSendable {
        /// The URL of the location containing the IdP metadata.
        case url(String)
        /// The full IdP metadata, in XML format.
        case xml(String)

        public init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            guard container.allKeys.count == 1, let key = container.allKeys.first else {
                let context = DecodingError.Context(
                    codingPath: container.codingPath,
                    debugDescription: "Expected exactly one key, but got \(container.allKeys.count)"
                )
                throw DecodingError.dataCorrupted(context)
            }
            switch key {
            case .url:
                let value = try container.decode(String.self, forKey: .url)
                self = .url(value)
            case .xml:
                let value = try container.decode(String.self, forKey: .xml)
                self = .xml(value)
            }
        }

        public func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            switch self {
            case .url(let value):
                try container.encode(value, forKey: .url)
            case .xml(let value):
                try container.encode(value, forKey: .xml)
            }
        }

        public func validate(name: String) throws {
            switch self {
            case .url(let value):
                try self.validate(value, name: "url", parent: name, max: 2048)
                try self.validate(value, name: "url", parent: name, min: 1)
            default:
                break
            }
        }

        private enum CodingKeys: String, CodingKey {
            case url
            case xml
        }
    }

    // MARK: Shapes

    public struct AssertionAttributes: AWSEncodableShape & AWSDecodableShape {
        /// The name of the attribute within the SAML assertion to use as the email names for SAML users.
        public let email: String?
        /// The name of the attribute within the SAML assertion to use as the user full "friendly" names for user groups.
        public let groups: String?
        /// The name of the attribute within the SAML assertion to use as the login names for SAML users.
        public let login: String?
        /// The name of the attribute within the SAML assertion to use as the user full "friendly" names for SAML users.
        public let name: String?
        /// The name of the attribute within the SAML assertion to use as the user full "friendly" names for the users' organizations.
        public let org: String?
        /// The name of the attribute within the SAML assertion to use as the user roles.
        public let role: String?

        public init(email: String? = nil, groups: String? = nil, login: String? = nil, name: String? = nil, org: String? = nil, role: String? = nil) {
            self.email = email
            self.groups = groups
            self.login = login
            self.name = name
            self.org = org
            self.role = role
        }

        public func validate(name: String) throws {
            try self.validate(self.email, name: "email", parent: name, max: 256)
            try self.validate(self.email, name: "email", parent: name, min: 1)
            try self.validate(self.groups, name: "groups", parent: name, max: 256)
            try self.validate(self.groups, name: "groups", parent: name, min: 1)
            try self.validate(self.login, name: "login", parent: name, max: 256)
            try self.validate(self.login, name: "login", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, max: 256)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.org, name: "org", parent: name, max: 256)
            try self.validate(self.org, name: "org", parent: name, min: 1)
            try self.validate(self.role, name: "role", parent: name, max: 256)
            try self.validate(self.role, name: "role", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case email
            case groups
            case login
            case name
            case org
            case role
        }
    }

    public struct AssociateLicenseRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "licenseType", location: .uri("licenseType")),
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The type of license to associate with the workspace.
        public let licenseType: LicenseType
        /// The ID of the workspace to associate the license with.
        public let workspaceId: String

        public init(licenseType: LicenseType, workspaceId: String) {
            self.licenseType = licenseType
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct AssociateLicenseResponse: AWSDecodableShape {
        /// A structure containing data about the workspace.
        public let workspace: WorkspaceDescription

        public init(workspace: WorkspaceDescription) {
            self.workspace = workspace
        }

        private enum CodingKeys: String, CodingKey {
            case workspace
        }
    }

    public struct AuthenticationDescription: AWSDecodableShape {
        /// A structure containing information about how this workspace works with  IAM Identity Center.
        public let awsSso: AwsSsoAuthentication?
        /// Specifies whether this workspace uses IAM Identity Center, SAML, or both methods  to authenticate users to use the Grafana console in the Amazon Managed Grafana  workspace.
        public let providers: [AuthenticationProviderTypes]
        /// A structure containing information about how this workspace works with  SAML, including what attributes within the assertion are to be mapped to  user information in the workspace.
        public let saml: SamlAuthentication?

        public init(awsSso: AwsSsoAuthentication? = nil, providers: [AuthenticationProviderTypes], saml: SamlAuthentication? = nil) {
            self.awsSso = awsSso
            self.providers = providers
            self.saml = saml
        }

        private enum CodingKeys: String, CodingKey {
            case awsSso
            case providers
            case saml
        }
    }

    public struct AuthenticationSummary: AWSDecodableShape {
        /// Specifies whether the workspace uses SAML, IAM Identity Center, or both methods for user authentication.
        public let providers: [AuthenticationProviderTypes]
        /// Specifies whether the workplace's user authentication method is fully configured.
        public let samlConfigurationStatus: SamlConfigurationStatus?

        public init(providers: [AuthenticationProviderTypes], samlConfigurationStatus: SamlConfigurationStatus? = nil) {
            self.providers = providers
            self.samlConfigurationStatus = samlConfigurationStatus
        }

        private enum CodingKeys: String, CodingKey {
            case providers
            case samlConfigurationStatus
        }
    }

    public struct AwsSsoAuthentication: AWSDecodableShape {
        /// The ID of the IAM Identity Center-managed application that is created by Amazon Managed Grafana.
        public let ssoClientId: String?

        public init(ssoClientId: String? = nil) {
            self.ssoClientId = ssoClientId
        }

        private enum CodingKeys: String, CodingKey {
            case ssoClientId
        }
    }

    public struct CreateWorkspaceApiKeyRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// Specifies the name of the key. Keynames must be unique to the workspace.
        public let keyName: String
        /// Specifies the permission level of the key. Valid values: VIEWER|EDITOR|ADMIN
        public let keyRole: String
        /// Specifies the time in seconds until the key expires. Keys can be valid for up to 30 days.
        public let secondsToLive: Int
        /// The ID of the workspace to create an API key.
        public let workspaceId: String

        public init(keyName: String, keyRole: String, secondsToLive: Int, workspaceId: String) {
            self.keyName = keyName
            self.keyRole = keyRole
            self.secondsToLive = secondsToLive
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.keyName, name: "keyName", parent: name, max: 100)
            try self.validate(self.keyName, name: "keyName", parent: name, min: 1)
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: String, CodingKey {
            case keyName
            case keyRole
            case secondsToLive
        }
    }

    public struct CreateWorkspaceApiKeyResponse: AWSDecodableShape {
        /// The key token. Use this value as a bearer token to  authenticate HTTP requests to the workspace.
        public let key: String
        /// The name of the key that was created.
        public let keyName: String
        /// The ID of the workspace that the key is valid for.
        public let workspaceId: String

        public init(key: String, keyName: String, workspaceId: String) {
            self.key = key
            self.keyName = keyName
            self.workspaceId = workspaceId
        }

        private enum CodingKeys: String, CodingKey {
            case key
            case keyName
            case workspaceId
        }
    }

    public struct CreateWorkspaceRequest: AWSEncodableShape {
        /// Specifies whether the workspace can access Amazon Web Services resources in this Amazon Web Services account only, or whether it can also access Amazon Web Services resources in other accounts in the same organization. If you specify ORGANIZATION, you must specify which organizational units the workspace can access in the workspaceOrganizationalUnits parameter.
        public let accountAccessType: AccountAccessType
        /// Specifies whether this workspace uses SAML 2.0, IAM Identity Center (successor to Single Sign-On), or both to authenticate  users for using the Grafana console within a workspace. For more information,  see User authentication in  Amazon Managed Grafana.
        public let authenticationProviders: [AuthenticationProviderTypes]
        /// A unique, case-sensitive, user-provided identifier to ensure the idempotency of the request.
        public let clientToken: String?
        /// The configuration string for the workspace that you create. For more information  about the format and configuration options available, see Working in your Grafana workspace.
        public let configuration: String?
        /// The name of an IAM role that already exists to use with Organizations to access Amazon Web Services data sources and notification channels in other accounts in an organization.
        public let organizationRoleName: String?
        /// If you specify SERVICE_MANAGED on AWS Grafana console, Amazon Managed Grafana automatically creates the IAM roles and provisions the permissions that the workspace needs to use Amazon Web Services data sources and notification channels. In the CLI mode, the permissionType SERVICE_MANAGED will not create the IAM role  for you. The ability for the Amazon Managed Grafana to create the IAM role on behalf of the user is supported only in the  Amazon Managed Grafana AWS console. Use only the CUSTOMER_MANAGED permission type when creating a workspace in the CLI.   If you specify CUSTOMER_MANAGED, you will manage those roles and permissions yourself. If you are creating this workspace in a member account of an organization that is not a delegated administrator account, and you want the workspace to access data sources in other Amazon Web Services accounts in the organization, you must choose CUSTOMER_MANAGED. For more information, see Amazon Managed Grafana permissions and policies for Amazon Web Services data sources and notification channels.
        public let permissionType: PermissionType
        /// The name of the CloudFormation stack set to use to generate IAM roles to be used for this workspace.
        public let stackSetName: String?
        /// The list of tags associated with the workspace.
        public let tags: [String: String]?
        /// The configuration settings for an Amazon VPC that contains data sources for your Grafana workspace to connect to.
        public let vpcConfiguration: VpcConfiguration?
        /// Specify the Amazon Web Services data sources that you want to be queried in this workspace. Specifying these data sources here enables Amazon Managed Grafana to create IAM roles and permissions that allow Amazon Managed Grafana to read data from these sources. You must still add them as data sources in the Grafana console in the workspace. If you don't specify a data source here, you can still add it as a data source in the workspace console later. However, you will then have to manually configure permissions for it.
        public let workspaceDataSources: [DataSourceType]?
        /// A description for the workspace. This is used only to help you identify this workspace. Pattern: ^[\\p{L}\\p{Z}\\p{N}\\p{P}]{0,2048}$
        public let workspaceDescription: String?
        /// The name for the workspace. It does not have to be unique.
        public let workspaceName: String?
        /// Specify the Amazon Web Services notification channels that you plan to use in this workspace. Specifying these  data sources here enables Amazon Managed Grafana to create IAM roles and permissions that allow  Amazon Managed Grafana to use these channels.
        public let workspaceNotificationDestinations: [NotificationDestinationType]?
        /// Specifies the organizational units that this workspace is allowed to use data sources from, if this workspace is in an account that is part of an organization.
        public let workspaceOrganizationalUnits: [String]?
        /// The workspace needs an IAM role that grants permissions to the Amazon Web Services resources that the  workspace will view data from. If you already have a role that you want to use, specify it here.  The permission type should be set to  CUSTOMER_MANAGED.
        public let workspaceRoleArn: String?

        public init(accountAccessType: AccountAccessType, authenticationProviders: [AuthenticationProviderTypes], clientToken: String? = CreateWorkspaceRequest.idempotencyToken(), configuration: String? = nil, organizationRoleName: String? = nil, permissionType: PermissionType, stackSetName: String? = nil, tags: [String: String]? = nil, vpcConfiguration: VpcConfiguration? = nil, workspaceDataSources: [DataSourceType]? = nil, workspaceDescription: String? = nil, workspaceName: String? = nil, workspaceNotificationDestinations: [NotificationDestinationType]? = nil, workspaceOrganizationalUnits: [String]? = nil, workspaceRoleArn: String? = nil) {
            self.accountAccessType = accountAccessType
            self.authenticationProviders = authenticationProviders
            self.clientToken = clientToken
            self.configuration = configuration
            self.organizationRoleName = organizationRoleName
            self.permissionType = permissionType
            self.stackSetName = stackSetName
            self.tags = tags
            self.vpcConfiguration = vpcConfiguration
            self.workspaceDataSources = workspaceDataSources
            self.workspaceDescription = workspaceDescription
            self.workspaceName = workspaceName
            self.workspaceNotificationDestinations = workspaceNotificationDestinations
            self.workspaceOrganizationalUnits = workspaceOrganizationalUnits
            self.workspaceRoleArn = workspaceRoleArn
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[!-~]{1,64}$")
            try self.validate(self.configuration, name: "configuration", parent: name, max: 65536)
            try self.validate(self.configuration, name: "configuration", parent: name, min: 2)
            try self.validate(self.organizationRoleName, name: "organizationRoleName", parent: name, max: 2048)
            try self.validate(self.organizationRoleName, name: "organizationRoleName", parent: name, min: 1)
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.vpcConfiguration?.validate(name: "\(name).vpcConfiguration")
            try self.validate(self.workspaceDescription, name: "workspaceDescription", parent: name, max: 2048)
            try self.validate(self.workspaceName, name: "workspaceName", parent: name, pattern: "^[a-zA-Z0-9-._~]{1,255}$")
            try self.validate(self.workspaceRoleArn, name: "workspaceRoleArn", parent: name, max: 2048)
            try self.validate(self.workspaceRoleArn, name: "workspaceRoleArn", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case accountAccessType
            case authenticationProviders
            case clientToken
            case configuration
            case organizationRoleName
            case permissionType
            case stackSetName
            case tags
            case vpcConfiguration
            case workspaceDataSources
            case workspaceDescription
            case workspaceName
            case workspaceNotificationDestinations
            case workspaceOrganizationalUnits
            case workspaceRoleArn
        }
    }

    public struct CreateWorkspaceResponse: AWSDecodableShape {
        /// A structure containing data about the workspace that was created.
        public let workspace: WorkspaceDescription

        public init(workspace: WorkspaceDescription) {
            self.workspace = workspace
        }

        private enum CodingKeys: String, CodingKey {
            case workspace
        }
    }

    public struct DeleteWorkspaceApiKeyRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "keyName", location: .uri("keyName")),
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The name of the API key to delete.
        public let keyName: String
        /// The ID of the workspace to delete.
        public let workspaceId: String

        public init(keyName: String, workspaceId: String) {
            self.keyName = keyName
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.keyName, name: "keyName", parent: name, max: 100)
            try self.validate(self.keyName, name: "keyName", parent: name, min: 1)
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteWorkspaceApiKeyResponse: AWSDecodableShape {
        /// The name of the key that was deleted.
        public let keyName: String
        /// The ID of the workspace where the key was deleted.
        public let workspaceId: String

        public init(keyName: String, workspaceId: String) {
            self.keyName = keyName
            self.workspaceId = workspaceId
        }

        private enum CodingKeys: String, CodingKey {
            case keyName
            case workspaceId
        }
    }

    public struct DeleteWorkspaceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The ID of the workspace to delete.
        public let workspaceId: String

        public init(workspaceId: String) {
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteWorkspaceResponse: AWSDecodableShape {
        /// A structure containing information about the workspace that was deleted.
        public let workspace: WorkspaceDescription

        public init(workspace: WorkspaceDescription) {
            self.workspace = workspace
        }

        private enum CodingKeys: String, CodingKey {
            case workspace
        }
    }

    public struct DescribeWorkspaceAuthenticationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The ID of the workspace to return authentication information about.
        public let workspaceId: String

        public init(workspaceId: String) {
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DescribeWorkspaceAuthenticationResponse: AWSDecodableShape {
        /// A structure containing information about the authentication methods used in  the workspace.
        public let authentication: AuthenticationDescription

        public init(authentication: AuthenticationDescription) {
            self.authentication = authentication
        }

        private enum CodingKeys: String, CodingKey {
            case authentication
        }
    }

    public struct DescribeWorkspaceConfigurationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The ID of the workspace to get configuration information for.
        public let workspaceId: String

        public init(workspaceId: String) {
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DescribeWorkspaceConfigurationResponse: AWSDecodableShape {
        /// The configuration string for the workspace that you requested. For more information  about the format and configuration options available, see Working in your Grafana workspace.
        public let configuration: String

        public init(configuration: String) {
            self.configuration = configuration
        }

        private enum CodingKeys: String, CodingKey {
            case configuration
        }
    }

    public struct DescribeWorkspaceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The ID of the workspace to display information about.
        public let workspaceId: String

        public init(workspaceId: String) {
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DescribeWorkspaceResponse: AWSDecodableShape {
        /// A structure containing information about the workspace.
        public let workspace: WorkspaceDescription

        public init(workspace: WorkspaceDescription) {
            self.workspace = workspace
        }

        private enum CodingKeys: String, CodingKey {
            case workspace
        }
    }

    public struct DisassociateLicenseRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "licenseType", location: .uri("licenseType")),
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The type of license to remove from the workspace.
        public let licenseType: LicenseType
        /// The ID of the workspace to remove the Grafana Enterprise license from.
        public let workspaceId: String

        public init(licenseType: LicenseType, workspaceId: String) {
            self.licenseType = licenseType
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DisassociateLicenseResponse: AWSDecodableShape {
        /// A structure containing information about the workspace.
        public let workspace: WorkspaceDescription

        public init(workspace: WorkspaceDescription) {
            self.workspace = workspace
        }

        private enum CodingKeys: String, CodingKey {
            case workspace
        }
    }

    public struct ListPermissionsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "groupId", location: .querystring("groupId")),
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken")),
            AWSMemberEncoding(label: "userId", location: .querystring("userId")),
            AWSMemberEncoding(label: "userType", location: .querystring("userType")),
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// (Optional) Limits the results to only the group that matches this ID.
        public let groupId: String?
        /// The maximum number of results to include in the response.
        public let maxResults: Int?
        /// The token to use when requesting the next set of results. You received this token from a previous  ListPermissions operation.
        public let nextToken: String?
        /// (Optional) Limits the results to only the user that matches this ID.
        public let userId: String?
        /// (Optional) If you specify SSO_USER, then only the permissions of IAM Identity Center users are returned. If you specify SSO_GROUP, only the permissions of IAM Identity Center groups are returned.
        public let userType: UserType?
        /// The ID of the workspace to list permissions for. This parameter is required.
        public let workspaceId: String

        public init(groupId: String? = nil, maxResults: Int? = nil, nextToken: String? = nil, userId: String? = nil, userType: UserType? = nil, workspaceId: String) {
            self.groupId = groupId
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.userId = userId
            self.userType = userType
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.groupId, name: "groupId", parent: name, max: 47)
            try self.validate(self.groupId, name: "groupId", parent: name, min: 1)
            try self.validate(self.userId, name: "userId", parent: name, max: 47)
            try self.validate(self.userId, name: "userId", parent: name, min: 1)
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListPermissionsResponse: AWSDecodableShape {
        /// The token to use in a subsequent ListPermissions operation to return the next set of results.
        public let nextToken: String?
        /// The permissions returned by the operation.
        public let permissions: [PermissionEntry]

        public init(nextToken: String? = nil, permissions: [PermissionEntry]) {
            self.nextToken = nextToken
            self.permissions = permissions
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case permissions
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The ARN of the resource the list of tags are associated with.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// The list of tags that are associated with the resource.
        public let tags: [String: String]?

        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct ListWorkspacesRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken"))
        ]

        /// The maximum number of workspaces to include in the results.
        public let maxResults: Int?
        /// The token for the next set of workspaces to return. (You receive this token from a previous ListWorkspaces operation.)
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListWorkspacesResponse: AWSDecodableShape {
        /// The token to use when requesting the next set of workspaces.
        public let nextToken: String?
        /// An array of structures that contain some information about the workspaces in the account.
        public let workspaces: [WorkspaceSummary]

        public init(nextToken: String? = nil, workspaces: [WorkspaceSummary]) {
            self.nextToken = nextToken
            self.workspaces = workspaces
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case workspaces
        }
    }

    public struct PermissionEntry: AWSDecodableShape {
        /// Specifies whether the user or group has the Admin, Editor, or Viewer role.
        public let role: Role
        /// A structure with the ID of the user or group with this role.
        public let user: User

        public init(role: Role, user: User) {
            self.role = role
            self.user = user
        }

        private enum CodingKeys: String, CodingKey {
            case role
            case user
        }
    }

    public struct RoleValues: AWSEncodableShape & AWSDecodableShape {
        /// A list of groups from the SAML assertion attribute to grant the Grafana Admin role to.
        public let admin: [String]?
        /// A list of groups from the SAML assertion attribute to grant the Grafana Editor role to.
        public let editor: [String]?

        public init(admin: [String]? = nil, editor: [String]? = nil) {
            self.admin = admin
            self.editor = editor
        }

        public func validate(name: String) throws {
            try self.admin?.forEach {
                try validate($0, name: "admin[]", parent: name, max: 256)
                try validate($0, name: "admin[]", parent: name, min: 1)
            }
            try self.editor?.forEach {
                try validate($0, name: "editor[]", parent: name, max: 256)
                try validate($0, name: "editor[]", parent: name, min: 1)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case admin
            case editor
        }
    }

    public struct SamlAuthentication: AWSDecodableShape {
        /// A structure containing details about how this workspace works with  SAML.
        public let configuration: SamlConfiguration?
        /// Specifies whether the workspace's SAML configuration is complete.
        public let status: SamlConfigurationStatus

        public init(configuration: SamlConfiguration? = nil, status: SamlConfigurationStatus) {
            self.configuration = configuration
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case configuration
            case status
        }
    }

    public struct SamlConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Lists which organizations defined in the SAML assertion are allowed to use the Amazon Managed Grafana workspace. If this is empty, all organizations in the assertion attribute have access.
        public let allowedOrganizations: [String]?
        /// A structure that defines which attributes in the SAML assertion are to be used to define information about the users authenticated by that IdP to use the workspace.
        public let assertionAttributes: AssertionAttributes?
        /// A structure containing the identity provider (IdP) metadata used to integrate the identity provider with this workspace.
        public let idpMetadata: IdpMetadata
        /// How long a sign-on session by a SAML user is valid, before the user has to sign on again.
        public let loginValidityDuration: Int?
        /// A structure containing arrays that map group names in the SAML assertion to the  Grafana Admin and Editor roles in the workspace.
        public let roleValues: RoleValues?

        public init(allowedOrganizations: [String]? = nil, assertionAttributes: AssertionAttributes? = nil, idpMetadata: IdpMetadata, loginValidityDuration: Int? = nil, roleValues: RoleValues? = nil) {
            self.allowedOrganizations = allowedOrganizations
            self.assertionAttributes = assertionAttributes
            self.idpMetadata = idpMetadata
            self.loginValidityDuration = loginValidityDuration
            self.roleValues = roleValues
        }

        public func validate(name: String) throws {
            try self.allowedOrganizations?.forEach {
                try validate($0, name: "allowedOrganizations[]", parent: name, max: 256)
                try validate($0, name: "allowedOrganizations[]", parent: name, min: 1)
            }
            try self.assertionAttributes?.validate(name: "\(name).assertionAttributes")
            try self.idpMetadata.validate(name: "\(name).idpMetadata")
            try self.roleValues?.validate(name: "\(name).roleValues")
        }

        private enum CodingKeys: String, CodingKey {
            case allowedOrganizations
            case assertionAttributes
            case idpMetadata
            case loginValidityDuration
            case roleValues
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The ARN of the resource the tag is associated with.
        public let resourceArn: String
        /// The list of tag keys and values to associate with the resource.  You can associate tag keys only, tags (key and values) only or a combination of tag keys and tags.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring("tagKeys"))
        ]

        /// The ARN of the resource the tag association is removed from.
        public let resourceArn: String
        /// The key values of the tag to be removed from the resource.
        public let tagKeys: [String]

        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateError: AWSDecodableShape {
        /// Specifies which permission update caused the error.
        public let causedBy: UpdateInstruction
        /// The error code.
        public let code: Int
        /// The message for this error.
        public let message: String

        public init(causedBy: UpdateInstruction, code: Int, message: String) {
            self.causedBy = causedBy
            self.code = code
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case causedBy
            case code
            case message
        }
    }

    public struct UpdateInstruction: AWSEncodableShape & AWSDecodableShape {
        /// Specifies whether this update is to add or revoke role permissions.
        public let action: UpdateAction
        /// The role to add or revoke for the user or the group specified in users.
        public let role: Role
        /// A structure that specifies the user or group to add or revoke the role for.
        public let users: [User]

        public init(action: UpdateAction, role: Role, users: [User]) {
            self.action = action
            self.role = role
            self.users = users
        }

        public func validate(name: String) throws {
            try self.users.forEach {
                try $0.validate(name: "\(name).users[]")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case action
            case role
            case users
        }
    }

    public struct UpdatePermissionsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// An array of structures that contain the permission updates to make.
        public let updateInstructionBatch: [UpdateInstruction]
        /// The ID of the workspace to update.
        public let workspaceId: String

        public init(updateInstructionBatch: [UpdateInstruction], workspaceId: String) {
            self.updateInstructionBatch = updateInstructionBatch
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.updateInstructionBatch.forEach {
                try $0.validate(name: "\(name).updateInstructionBatch[]")
            }
            try self.validate(self.updateInstructionBatch, name: "updateInstructionBatch", parent: name, max: 20)
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: String, CodingKey {
            case updateInstructionBatch
        }
    }

    public struct UpdatePermissionsResponse: AWSDecodableShape {
        /// An array of structures that contain the errors from the operation, if any.
        public let errors: [UpdateError]

        public init(errors: [UpdateError]) {
            self.errors = errors
        }

        private enum CodingKeys: String, CodingKey {
            case errors
        }
    }

    public struct UpdateWorkspaceAuthenticationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// Specifies whether this workspace uses SAML 2.0, IAM Identity Center (successor to Single Sign-On), or both to authenticate  users for using the Grafana console within a workspace. For more information,  see User authentication in  Amazon Managed Grafana.
        public let authenticationProviders: [AuthenticationProviderTypes]
        /// If the workspace uses SAML, use this structure to map SAML assertion attributes to workspace user information and  define which groups in the assertion attribute are to have the Admin and Editor roles in the workspace.
        public let samlConfiguration: SamlConfiguration?
        /// The ID of the workspace to update the authentication for.
        public let workspaceId: String

        public init(authenticationProviders: [AuthenticationProviderTypes], samlConfiguration: SamlConfiguration? = nil, workspaceId: String) {
            self.authenticationProviders = authenticationProviders
            self.samlConfiguration = samlConfiguration
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.samlConfiguration?.validate(name: "\(name).samlConfiguration")
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: String, CodingKey {
            case authenticationProviders
            case samlConfiguration
        }
    }

    public struct UpdateWorkspaceAuthenticationResponse: AWSDecodableShape {
        /// A structure that describes the user authentication for this workspace after the update is made.
        public let authentication: AuthenticationDescription

        public init(authentication: AuthenticationDescription) {
            self.authentication = authentication
        }

        private enum CodingKeys: String, CodingKey {
            case authentication
        }
    }

    public struct UpdateWorkspaceConfigurationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// The new configuration string for the workspace. For more information  about the format and configuration options available, see Working in your Grafana workspace.
        public let configuration: String
        /// The ID of the workspace to update.
        public let workspaceId: String

        public init(configuration: String, workspaceId: String) {
            self.configuration = configuration
            self.workspaceId = workspaceId
        }

        public func validate(name: String) throws {
            try self.validate(self.configuration, name: "configuration", parent: name, max: 65536)
            try self.validate(self.configuration, name: "configuration", parent: name, min: 2)
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
        }

        private enum CodingKeys: String, CodingKey {
            case configuration
        }
    }

    public struct UpdateWorkspaceConfigurationResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateWorkspaceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "workspaceId", location: .uri("workspaceId"))
        ]

        /// Specifies whether the workspace can access Amazon Web Services resources in this Amazon Web Services account only, or whether it can also access Amazon Web Services resources in other accounts in the same organization. If you specify ORGANIZATION, you must specify which organizational units the workspace can access in the workspaceOrganizationalUnits parameter.
        public let accountAccessType: AccountAccessType?
        /// The name of an IAM role that already exists to use to access resources through Organizations.
        public let organizationRoleName: String?
        /// If you specify Service Managed, Amazon Managed Grafana automatically creates the IAM roles and provisions the permissions that the workspace needs to use Amazon Web Services data sources and notification channels. If you specify CUSTOMER_MANAGED, you will manage those roles and permissions yourself. If you are creating this workspace in a member account of an organization and that account is not a delegated administrator account, and you want the workspace to access data sources in other Amazon Web Services accounts in the organization, you must choose CUSTOMER_MANAGED. For more information, see Amazon Managed Grafana permissions and policies for Amazon Web Services data sources and notification channels
        public let permissionType: PermissionType?
        /// Whether to remove the VPC configuration from the workspace. Setting this to true and providing a vpcConfiguration to set  will return an error.
        public let removeVpcConfiguration: Bool?
        /// The name of the CloudFormation stack set to use to generate IAM roles to be used for this workspace.
        public let stackSetName: String?
        /// The configuration settings for an Amazon VPC that contains data sources for your Grafana workspace to connect to.
        public let vpcConfiguration: VpcConfiguration?
        /// Specify the Amazon Web Services data sources that you want to be queried in this workspace. Specifying these data sources here enables Amazon Managed Grafana to create IAM roles and permissions that allow Amazon Managed Grafana to read data from these sources. You must still add them as data sources in the Grafana console in the workspace. If you don't specify a data source here, you can still add it as a data source later in the workspace console. However, you will then have to manually configure permissions for it.
        public let workspaceDataSources: [DataSourceType]?
        /// A description for the workspace. This is used only to help you identify this workspace.
        public let workspaceDescription: String?
        /// The ID of the workspace to update.
        public let workspaceId: String
        /// A new name for the workspace to update.
        public let workspaceName: String?
        /// Specify the Amazon Web Services notification channels that you plan to use in this workspace. Specifying these  data sources here enables Amazon Managed Grafana to create IAM roles and permissions that allow  Amazon Managed Grafana to use these channels.
        public let workspaceNotificationDestinations: [NotificationDestinationType]?
        /// Specifies the organizational units that this workspace is allowed to use data sources from, if this workspace is in an account that is part of an organization.
        public let workspaceOrganizationalUnits: [String]?
        /// The workspace needs an IAM role that grants permissions to the Amazon Web Services resources that the  workspace will view data from. If you already have a role that you want to use, specify it here. If you omit this field and you specify some Amazon Web Services resources in workspaceDataSources or workspaceNotificationDestinations, a new IAM role with the necessary permissions is  automatically created.
        public let workspaceRoleArn: String?

        public init(accountAccessType: AccountAccessType? = nil, organizationRoleName: String? = nil, permissionType: PermissionType? = nil, removeVpcConfiguration: Bool? = nil, stackSetName: String? = nil, vpcConfiguration: VpcConfiguration? = nil, workspaceDataSources: [DataSourceType]? = nil, workspaceDescription: String? = nil, workspaceId: String, workspaceName: String? = nil, workspaceNotificationDestinations: [NotificationDestinationType]? = nil, workspaceOrganizationalUnits: [String]? = nil, workspaceRoleArn: String? = nil) {
            self.accountAccessType = accountAccessType
            self.organizationRoleName = organizationRoleName
            self.permissionType = permissionType
            self.removeVpcConfiguration = removeVpcConfiguration
            self.stackSetName = stackSetName
            self.vpcConfiguration = vpcConfiguration
            self.workspaceDataSources = workspaceDataSources
            self.workspaceDescription = workspaceDescription
            self.workspaceId = workspaceId
            self.workspaceName = workspaceName
            self.workspaceNotificationDestinations = workspaceNotificationDestinations
            self.workspaceOrganizationalUnits = workspaceOrganizationalUnits
            self.workspaceRoleArn = workspaceRoleArn
        }

        public func validate(name: String) throws {
            try self.validate(self.organizationRoleName, name: "organizationRoleName", parent: name, max: 2048)
            try self.validate(self.organizationRoleName, name: "organizationRoleName", parent: name, min: 1)
            try self.vpcConfiguration?.validate(name: "\(name).vpcConfiguration")
            try self.validate(self.workspaceDescription, name: "workspaceDescription", parent: name, max: 2048)
            try self.validate(self.workspaceId, name: "workspaceId", parent: name, pattern: "^g-[0-9a-f]{10}$")
            try self.validate(self.workspaceName, name: "workspaceName", parent: name, pattern: "^[a-zA-Z0-9-._~]{1,255}$")
            try self.validate(self.workspaceRoleArn, name: "workspaceRoleArn", parent: name, max: 2048)
            try self.validate(self.workspaceRoleArn, name: "workspaceRoleArn", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case accountAccessType
            case organizationRoleName
            case permissionType
            case removeVpcConfiguration
            case stackSetName
            case vpcConfiguration
            case workspaceDataSources
            case workspaceDescription
            case workspaceName
            case workspaceNotificationDestinations
            case workspaceOrganizationalUnits
            case workspaceRoleArn
        }
    }

    public struct UpdateWorkspaceResponse: AWSDecodableShape {
        /// A structure containing data about the workspace that was created.
        public let workspace: WorkspaceDescription

        public init(workspace: WorkspaceDescription) {
            self.workspace = workspace
        }

        private enum CodingKeys: String, CodingKey {
            case workspace
        }
    }

    public struct User: AWSEncodableShape & AWSDecodableShape {
        /// The ID of the user or group. Pattern: ^([0-9a-fA-F]{10}-|)[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$
        public let id: String
        /// Specifies whether this is a single user or a group.
        public let type: UserType

        public init(id: String, type: UserType) {
            self.id = id
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.id, name: "id", parent: name, max: 47)
            try self.validate(self.id, name: "id", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case id
            case type
        }
    }

    public struct VpcConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// The list of Amazon EC2 security group IDs attached to the Amazon VPC for your Grafana workspace to connect.
        public let securityGroupIds: [String]
        /// The list of Amazon EC2 subnet IDs created in the Amazon VPC for  your Grafana workspace to connect.
        public let subnetIds: [String]

        public init(securityGroupIds: [String], subnetIds: [String]) {
            self.securityGroupIds = securityGroupIds
            self.subnetIds = subnetIds
        }

        public func validate(name: String) throws {
            try self.securityGroupIds.forEach {
                try validate($0, name: "securityGroupIds[]", parent: name, max: 255)
            }
            try self.validate(self.securityGroupIds, name: "securityGroupIds", parent: name, max: 100)
            try self.validate(self.securityGroupIds, name: "securityGroupIds", parent: name, min: 1)
            try self.subnetIds.forEach {
                try validate($0, name: "subnetIds[]", parent: name, max: 255)
            }
            try self.validate(self.subnetIds, name: "subnetIds", parent: name, max: 100)
            try self.validate(self.subnetIds, name: "subnetIds", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case securityGroupIds
            case subnetIds
        }
    }

    public struct WorkspaceDescription: AWSDecodableShape {
        /// Specifies whether the workspace can access Amazon Web Services resources in this Amazon Web Services account only, or whether it can also access Amazon Web Services resources in other accounts in the same organization. If this is ORGANIZATION, the workspaceOrganizationalUnits parameter specifies which organizational units the workspace can access.
        public let accountAccessType: AccountAccessType?
        /// A structure that describes whether the workspace uses SAML, IAM Identity Center, or both methods for user authentication.
        public let authentication: AuthenticationSummary
        /// The date that the workspace was created.
        public let created: Date
        /// Specifies the Amazon Web Services data sources that have been configured to have IAM  roles and permissions created to allow  Amazon Managed Grafana to read data from these sources.
        public let dataSources: [DataSourceType]
        /// The user-defined description of the workspace.
        public let description: String?
        /// The URL that users can use to access the Grafana console in the workspace.
        public let endpoint: String
        /// Specifies whether this workspace has already fully used its free trial for Grafana Enterprise.
        public let freeTrialConsumed: Bool?
        /// If this workspace is currently in the free trial period for Grafana Enterprise, this value specifies when that free trial ends.
        public let freeTrialExpiration: Date?
        /// The version of Grafana supported in this workspace.
        public let grafanaVersion: String
        /// The unique ID of this workspace.
        public let id: String
        /// If this workspace has a full Grafana Enterprise license, this specifies when the license ends and will need to be renewed.
        public let licenseExpiration: Date?
        /// Specifies whether this workspace has a full Grafana Enterprise license or a free trial license.
        public let licenseType: LicenseType?
        /// The most recent date that the workspace was modified.
        public let modified: Date
        /// The name of the workspace.
        public let name: String?
        /// The Amazon Web Services notification channels that Amazon Managed Grafana can automatically create IAM  roles and permissions for, to allow  Amazon Managed Grafana to use these channels.
        public let notificationDestinations: [NotificationDestinationType]?
        /// Specifies the organizational units that this workspace is allowed to use data sources from, if this workspace is in an account that is part of an organization.
        public let organizationalUnits: [String]?
        /// The name of the IAM role that is used to access resources through Organizations.
        public let organizationRoleName: String?
        /// If this is Service Managed, Amazon Managed Grafana automatically creates the IAM roles  and provisions the permissions that the workspace needs to use Amazon Web Services data sources and notification channels. If this is CUSTOMER_MANAGED, you manage those roles and permissions yourself. If you are creating this workspace in a member account of an organization and that account is not a delegated administrator account, and you want the workspace to access data sources in other Amazon Web Services accounts in the organization, you must choose CUSTOMER_MANAGED. For more information, see Amazon Managed Grafana permissions and policies for Amazon Web Services data sources and notification channels
        public let permissionType: PermissionType?
        /// The name of the CloudFormation stack set that is used to generate IAM roles to be used for this workspace.
        public let stackSetName: String?
        /// The current status of the workspace.
        public let status: WorkspaceStatus
        /// The list of tags associated with the workspace.
        public let tags: [String: String]?
        /// The configuration for connecting to data sources in a private VPC  (Amazon Virtual Private Cloud).
        public let vpcConfiguration: VpcConfiguration?
        /// The IAM role that grants permissions to the Amazon Web Services resources that the  workspace will view data from. This role must already exist.
        public let workspaceRoleArn: String?

        public init(accountAccessType: AccountAccessType? = nil, authentication: AuthenticationSummary, created: Date, dataSources: [DataSourceType], description: String? = nil, endpoint: String, freeTrialConsumed: Bool? = nil, freeTrialExpiration: Date? = nil, grafanaVersion: String, id: String, licenseExpiration: Date? = nil, licenseType: LicenseType? = nil, modified: Date, name: String? = nil, notificationDestinations: [NotificationDestinationType]? = nil, organizationalUnits: [String]? = nil, organizationRoleName: String? = nil, permissionType: PermissionType? = nil, stackSetName: String? = nil, status: WorkspaceStatus, tags: [String: String]? = nil, vpcConfiguration: VpcConfiguration? = nil, workspaceRoleArn: String? = nil) {
            self.accountAccessType = accountAccessType
            self.authentication = authentication
            self.created = created
            self.dataSources = dataSources
            self.description = description
            self.endpoint = endpoint
            self.freeTrialConsumed = freeTrialConsumed
            self.freeTrialExpiration = freeTrialExpiration
            self.grafanaVersion = grafanaVersion
            self.id = id
            self.licenseExpiration = licenseExpiration
            self.licenseType = licenseType
            self.modified = modified
            self.name = name
            self.notificationDestinations = notificationDestinations
            self.organizationalUnits = organizationalUnits
            self.organizationRoleName = organizationRoleName
            self.permissionType = permissionType
            self.stackSetName = stackSetName
            self.status = status
            self.tags = tags
            self.vpcConfiguration = vpcConfiguration
            self.workspaceRoleArn = workspaceRoleArn
        }

        private enum CodingKeys: String, CodingKey {
            case accountAccessType
            case authentication
            case created
            case dataSources
            case description
            case endpoint
            case freeTrialConsumed
            case freeTrialExpiration
            case grafanaVersion
            case id
            case licenseExpiration
            case licenseType
            case modified
            case name
            case notificationDestinations
            case organizationalUnits
            case organizationRoleName
            case permissionType
            case stackSetName
            case status
            case tags
            case vpcConfiguration
            case workspaceRoleArn
        }
    }

    public struct WorkspaceSummary: AWSDecodableShape {
        /// A structure containing information about the authentication methods used in  the workspace.
        public let authentication: AuthenticationSummary
        /// The date that the workspace was created.
        public let created: Date
        /// The customer-entered description of the workspace.
        public let description: String?
        /// The URL endpoint to use to access the Grafana console in the workspace.
        public let endpoint: String
        /// The Grafana version that the workspace is running.
        public let grafanaVersion: String
        /// The unique ID of the workspace.
        public let id: String
        /// The most recent date that the workspace was modified.
        public let modified: Date
        /// The name of the workspace.
        public let name: String?
        /// The Amazon Web Services notification channels that Amazon Managed Grafana can automatically create IAM roles and permissions for, which allows Amazon Managed Grafana to use these channels.
        public let notificationDestinations: [NotificationDestinationType]?
        /// The current status of the workspace.
        public let status: WorkspaceStatus
        /// The list of tags associated with the workspace.
        public let tags: [String: String]?

        public init(authentication: AuthenticationSummary, created: Date, description: String? = nil, endpoint: String, grafanaVersion: String, id: String, modified: Date, name: String? = nil, notificationDestinations: [NotificationDestinationType]? = nil, status: WorkspaceStatus, tags: [String: String]? = nil) {
            self.authentication = authentication
            self.created = created
            self.description = description
            self.endpoint = endpoint
            self.grafanaVersion = grafanaVersion
            self.id = id
            self.modified = modified
            self.name = name
            self.notificationDestinations = notificationDestinations
            self.status = status
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case authentication
            case created
            case description
            case endpoint
            case grafanaVersion
            case id
            case modified
            case name
            case notificationDestinations
            case status
            case tags
        }
    }
}

// MARK: - Errors

/// Error enum for Grafana
public struct GrafanaErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize Grafana
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You do not have sufficient permissions to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// A resource was in an inconsistent state during an update or a deletion.
    public static var conflictException: Self { .init(.conflictException) }
    /// Unexpected error while processing the request. Retry the request.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The request references a resource that does not exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// The request would cause a service quota to be exceeded.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request was denied because of request throttling. Retry the request.
    public static var throttlingException: Self { .init(.throttlingException) }
    /// The value of a parameter in the request caused an error.
    public static var validationException: Self { .init(.validationException) }
}

extension GrafanaErrorType: Equatable {
    public static func == (lhs: GrafanaErrorType, rhs: GrafanaErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension GrafanaErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
